package org.phalanx.servlet.webmessages;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;

import javax.imageio.stream.FileCacheImageInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.phalanx.game.units.PhalanxMapUnit;
import org.phalanx.game.units.PhalanxMapUnitSet;
import org.phalanx.map.MapTile;
import org.phalanx.map.MapTileSet;
import org.phalanx.map.PhalanxMap;
import org.phalanx.server.PhalanxServer;
import org.phalanx.server.ServerCache.CacheManager;
import org.phalanx.server.ServerCache.Cacheable;
import org.phalanx.server.game.PhalanxGameSettings;
import org.phalanx.server.game.PhalanxMapCacheWrapper;
import org.phalanx.servlet.websession.ServletAuthenticatorManager;
import org.phalanx.zip.ZipFileArchiveReader;

public class MapMediaLoaderContext implements WebMessageable{
	public static String CONTEXT = "mapresource";
	private PhalanxServer pServer;
	private String fileType = "png";

	public MapMediaLoaderContext(PhalanxServer pServer){
		this.pServer = pServer;
	}

	@Override
	public void onContextLoadable(String context, Cookie authCookie,
			HttpServletRequest req, HttpServletResponse resp) {
		if (context.equals(CONTEXT)){
			ServletAuthenticatorManager s = new ServletAuthenticatorManager(pServer);

			if (authCookie != null && s.authenticate(authCookie) != null){
				String mapName = req.getParameter("mapname");
				String tileName = req.getParameter("tilename");
				String gameUnitName = req.getParameter("gameunit");
				String gameid = req.getParameter("gameid");
				String getBuildPoint = req.getParameter("bp");

				if (tileName != null){

					if (mapName != null && tileName != null){
						byte[] imageData = loadTileData(mapName,tileName);

						if (imageData.length > 0){
							try {
								resp.setContentType("image/" + fileType);
								resp.getOutputStream().write(imageData);
							} catch (IOException ie){}
						}
					} // if (mapName != null && tileName != null)
				} // tileName == null
				else if (gameUnitName != null){
					try {
						byte[] imageData = loadGameUnitData(Integer.valueOf(gameid), gameUnitName);

						if (imageData.length > 0){
							resp.setContentType("image/" + fileType);
							resp.getOutputStream().write(imageData);
						}
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				else if (getBuildPoint != null){
					try {
						byte[] imageData = getBuildPointGraphic();

						if (imageData.length > 0){
							resp.setContentType("image/" + fileType);
							resp.getOutputStream().write(imageData);
						}
					} catch (IOException ie){
						ie.printStackTrace();
					}
				}
			}
		}

	}

	private byte[] loadTileData(String mapName, String tileName){
		byte[] b = new byte[0];
		CacheManager cacheMgr = pServer.getCacheManager();

		PhalanxMapCacheWrapper pMapWrap = (PhalanxMapCacheWrapper)cacheMgr.getElement("PhalanxMapCache", mapName);

		if (pMapWrap != null && pMapWrap.getMap() != null){
			PhalanxMap pMap = pMapWrap.getMap();
			pMapWrap.setLastAccess(new Date());
			MapTileSet tileSet = pMap.getMapTileSet();

			if (tileSet.getTileSetName() == null){
				tileSet = pServer.getMapManager().getDefaultTileSet();
			}

			if (tileSet.getMapTileByName(tileName) != null){
				MapTile t = tileSet.getMapTileByName(tileName);

				String filePath = t.getImageReference();

				if (filePath.length() > 3){
					fileType = filePath.substring(filePath.length() - 3);
				}

				try {
					ZipFileArchiveReader z = new ZipFileArchiveReader(tileSet.getTileSetArchiveFile());
					b = new byte[z.getByteSize()];
					b = z.getArchivedFile(filePath);
				} catch (IOException ie){ie.printStackTrace();}
			}
		}
		return b;
	}

	private byte[] loadGameUnitData(Integer gameid, String refName){
		// Won't load on a map by map basis for now because the unit set will be the same
		// for every game until we enable modding on a map level
		byte[] b = new byte[0];
		CacheManager cacheMgr = PhalanxServer.getServerInstance().getCacheManager();

		PhalanxGameSettings settings = (PhalanxGameSettings)cacheMgr.getElement("GameListCache", gameid);

		if (settings != null){
			PhalanxMapUnitSet uSet = settings.getUnitSet();

			PhalanxMapUnit oneUnit = uSet.getMapUnit(refName);

			try {
				if (oneUnit != null){
					File f = new File(oneUnit.getUnitReferenceName());
					b = new byte[(int)f.length()];

					DataInputStream is = new DataInputStream(new FileInputStream(oneUnit.getUnitReferenceName()));
					fileType = oneUnit.getUnitReferenceName().substring(oneUnit.getUnitReferenceName().length() - 3);

					is.readFully(b);

				}
			} catch (IOException ie){}
		}

		return b;
	}

	private byte[] getBuildPointGraphic(){
		byte[] b = new byte[0];
		String phalanxRootDir = PhalanxServer.getServerInstance().getRootDirectory() + "misc/";
		String fileName = "buildpoint.png";

		try {
			File f = new File(phalanxRootDir + fileName);
			b = new byte[(int)f.length()];

			DataInputStream is = new DataInputStream(new FileInputStream(f.getAbsolutePath()));
			fileType = "png";

			is.readFully(b);
		} catch (IOException ie){}

		return b;
	}

	private PhalanxGameSettings getGameIdByName(String gameName){
		// TODO: Move this function somewhere more useful

		PhalanxGameSettings settings = null;

		CacheManager cacheMgr = PhalanxServer.getServerInstance().getCacheManager(); 

		Iterator<Cacheable> i = cacheMgr.getCache("GameListCache").getInternalCacheTable().values().iterator();
		boolean isFound = false;

		while(i.hasNext() && !isFound){
			PhalanxGameSettings temp = (PhalanxGameSettings)i.next();

			if (temp.getGameName().equals(gameName)){
				isFound = true;
				settings = temp;
			}
		}

		return settings;
	}
}
